package com.panopset.flywheel;

import static com.panopset.Util.*;

import java.io.StringWriter;

import com.panopset.flywheel.gui.Commenum;

/**
 *
 * @author Karl Dinwiddie
 */
public abstract class Command {
    public final Template template;
    public final int lineNumber;
    Command next;
    Command prev;

    public Command(Template template) {
        this.template = template;
        this.lineNumber = template.sls.line;
    }

    protected abstract void resolve(StringWriter sw);

    public void resolveCommand(StringWriter sw) {
        template.flywheel.stepResolve(this);
        resolve(sw);
    }

    public abstract String getDescription();

    @Override
    public String toString() {
        StringWriter sw = new StringWriter();
        sw.append(getDescription());
        return sw.toString();
    }

    public static class Builder {
        private Template  template;
        private String  source;
        private int     closeDirectiveLoc;
        private Command command;

        /**
         * @param template
         * @return Builder
         */
        public Builder template(Template template) {
            this.template = template;
            return this;
        }

        /**
         * @param source
         * @return Builder
         */
        public Builder source(String source, int closeDirectiveLoc) {
            this.source = source;
            this.closeDirectiveLoc = closeDirectiveLoc;
            return this;
        }

        public Builder command(Command command) {
            this.command = command;
            return this;
        }

        public Command construct() {
            Command rtn = null;
            if (command == null) {
                if (source == null) {
                    throw new RuntimeException(
                            x("Not enough information to create a command"));
                }
                String innerPiece = source.substring(template.flywheel.openDirective
                        .length(), closeDirectiveLoc);
                if (innerPiece.indexOf(template.flywheel.directive) == 0
                        && innerPiece.length() > 1) {
                    char cmd = innerPiece.substring(1, 2).charAt(0);
                    if (cmd == Commenum.FILE.charCode) {
                        rtn = new CommandFile(source, innerPiece, template);
                    } else if (cmd == Commenum.PUSH.charCode) {
                        rtn = new CommandPush(source, innerPiece, template);
                    } else if (cmd == Commenum.REPLACE.charCode) {
                        rtn = new CommandReplace(source, innerPiece, template);
                    } else if (cmd == Commenum.LIST.charCode) {
                        rtn = new CommandList(source, innerPiece, template);
                    } else if (cmd == Commenum.QUIT.charCode) {
                        rtn = new CommandQuit(source, template);
                    } else if (cmd == Commenum.TEXT.charCode) {
                        rtn = new CommandTemplate(source, innerPiece, template);
                    } else if (cmd == Commenum.EXECUTE.charCode) {
                        rtn = new CommandExecute(source, innerPiece, template);
                    } else {
                        throw new RuntimeException("Invalid directive: " + cmd);
                    }
                } else {
                    rtn = new CommandVariable(source, innerPiece, template);
                }
            } else {
                rtn = command;
            }
            return rtn;
        }
    }
}
